package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.AAttack;
import com.ruoyi.system.domain.AAttackLevel;
import com.ruoyi.system.domain.AScore;
import com.ruoyi.system.domain.AWzs;
import com.ruoyi.system.domain.vo.AttackIndexLevelVo;
import com.ruoyi.system.domain.vo.AttackIndexTypeVo;
import com.ruoyi.system.mapper.AAttackMapper;
import com.ruoyi.system.service.IAAttackLevelService;
import com.ruoyi.system.service.IAAttackService;
import com.ruoyi.system.service.IAScoreService;
import com.ruoyi.system.service.IAWzsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 攻击评估Service业务层处理
 *
 * @author ruoyi
 * @date 2020-07-08
 */
@Service
public class AAttackServiceImpl implements IAAttackService {
    @Autowired
    private AAttackMapper aAttackMapper;

    @Autowired
    private IAWzsService iaWzsService;

    @Autowired
    private IAScoreService scoreService;

    @Autowired
    private IAAttackLevelService IAAttackLevelService;

    /**
     * 查询攻击评估
     *
     * @param aId 攻击评估ID
     * @return 攻击评估
     */
    @Override
    public AAttack selectAAttackById(Long aId) {

        AAttack attack = aAttackMapper.selectAAttackById(aId);
        //完整性要素记录 3
        AWzs wzs = new AWzs();
        wzs.setaId(aId);
        wzs.setC_type("3");

        attack.setWzxsObj(iaWzsService.selectAWzsList(wzs));

        //关联性要素记录 5
        AWzs glx = new AWzs();
        glx.setaId(aId);
        glx.setC_type("5");
        attack.setGlxsObj(iaWzsService.selectAWzsList(glx));

        AScore aScore = new AScore();
        aScore.setaId(aId);
        attack.setScoresObj(scoreService.selectAScoreList(aScore));
        return attack;
    }

    /**
     * 查询攻击评估列表
     *
     * @param aAttack 攻击评估
     * @return 攻击评估
     */
    @Override
    public List<AAttack> selectAAttackList(AAttack aAttack) {

        if ( aAttack.getParams().get("aTime") != null && !"".equals(aAttack.getParams().get("aTime")) ){
            String atime = (String) aAttack.getParams().get("aTime");
            aAttack.getParams().put("beginTime",atime.split(" ~ ")[0]);
            aAttack.getParams().put("endTime",atime.split(" ~ ")[1]);
        }

        return aAttackMapper.selectAAttackList(aAttack);
    }

    /**
     * 新增攻击评估
     *
     * @param aAttack 攻击评估
     * @return 结果
     */
    @Override
    public int insertAAttack(AAttack aAttack) {
        aAttack.setCreateTime(DateUtils.getNowDate());
        int code = aAttackMapper.insertAAttack(aAttack);
        List<Map> wzxs = aAttack.getWzxs();
        List<Map> glxs = aAttack.getGlxs();
        List<Map> scores = aAttack.getScores();

        //完整性要素记录 3
        if (wzxs != null) {
            for (Map wzx : wzxs) {
                AWzs aWzs = new AWzs(wzx, aAttack.getaId());
                aWzs.setC_type("3");
                iaWzsService.insertAWzs(aWzs);
            }
        }

        if (glxs != null) {
            //关联性要素记录 5
            for (Map wzx : glxs) {
                AWzs aWzs = new AWzs(wzx, aAttack.getaId());
                aWzs.setC_type("5");
                iaWzsService.insertAWzs(aWzs);
            }
        }


        if (scores != null) {
            for (Map score : scores) {
                AScore aScore = new AScore(score, aAttack.getaId());
                scoreService.insertAScore(aScore);
            }
        }

        return code;
    }

    /**
     * 修改攻击评估
     *
     * @param aAttack 攻击评估
     * @return 结果
     */
    @Override
    public int updateAAttack(AAttack aAttack) {
        aAttack.setUpdateTime(DateUtils.getNowDate());
        return aAttackMapper.updateAAttack(aAttack);
    }

    /**
     * 删除攻击评估对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteAAttackByIds(String ids) {
        return aAttackMapper.deleteAAttackByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除攻击评估信息
     *
     * @param aId 攻击评估ID
     * @return 结果
     */
    @Override
    public int deleteAAttackById(Long aId) {
        return aAttackMapper.deleteAAttackById(aId);
    }

    @Override
    public Map<String, Object> getIndexData(ModelMap mmap) {

        //头部数量统计
        DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        AAttack aAttack = new AAttack();
        List<AAttack> aAttacks = this.selectAAttackList(aAttack);
        //总数量
        Integer totalAttackAmount  = aAttacks.size();

        //昨日新增数量
        String today = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).format(formatters);
        String yesterday = LocalDateTime.of(LocalDate.now().plusDays(-1), LocalTime.MIN).format(formatters);
        Map<String, Object> params = new HashMap<>();
        params.put("beginTime",yesterday);
        params.put("endTime",today);
        aAttack.setParams(params);
        Integer yesterdayAttackAmount = this.selectAAttackList(aAttack).size();

        //七日内数量
        String sevenDaysAgo = LocalDateTime.now().plusDays(-6).format(formatters);
        params.put("beginTime",sevenDaysAgo);
        params.put("endTime",LocalDateTime.now().format(formatters));
        aAttack.setParams(params);
        Integer sevenDaysAttacksAmount = this.selectAAttackList(aAttack).size();

       //高概率数量
        AAttackLevel aAttackLevel = new AAttackLevel();
        aAttackLevel.setLevel("高");
        List<AAttackLevel> aAttackLevels = IAAttackLevelService.selectAAttackList(aAttackLevel);
        Integer highRateAttackAmount = aAttacks.stream().filter(thisAttack ->
                Double.parseDouble(thisAttack.getaRate()) >= aAttackLevels.get(0).getMinRate() &&
                        Double.parseDouble(thisAttack.getaRate()) < aAttackLevels.get(0).getMaxRate()).
                            collect(Collectors.toList()).size();



        //攻击概率分析
        List<AttackIndexLevelVo> attackIndexLevelData = new ArrayList<>();
        AAttackLevel aAttackLevel2 = new AAttackLevel();
        List<AAttackLevel> aAttackLevelList = IAAttackLevelService.selectAAttackList(aAttackLevel2);

        for (AAttackLevel attackLevel : aAttackLevelList) {
            String level = attackLevel.getLevel();
            Integer attackIndexLevelAmount = aAttacks.stream().filter(thisAttack ->
                    Double.parseDouble(thisAttack.getaRate()) >= attackLevel.getMinRate() &&
                            Double.parseDouble(thisAttack.getaRate()) < attackLevel.getMaxRate())
                                .collect(Collectors.toList()).size();

            AttackIndexLevelVo attackIndexLevelVo= new AttackIndexLevelVo();
            attackIndexLevelVo.setName(level);
            attackIndexLevelVo.setValue(attackIndexLevelAmount);
            attackIndexLevelData.add(attackIndexLevelVo);
        }

        //攻击类型占比数据
        List<AttackIndexTypeVo> attackTypeData = aAttackMapper.getAttackTypeData();



        //数量走势折线图
        //当前月份数值
        int monthValue = LocalDate.now().getMonthValue();
        //数据月份
        List<String> attackMonths = new ArrayList<String>();
        //攻击次数
        List<Integer> attackAmountEverMonth = new ArrayList<Integer>();
        for (int i = 1; i < monthValue + 1; i++) {
            attackMonths.add(i + " 月");
        }

       for (int i = monthValue - 1; i >= 0; i--) {
            String firstday = LocalDateTime.of(LocalDate.now().plusMonths(-i), LocalTime.MIN).with(TemporalAdjusters.firstDayOfMonth()).format(formatters);
            String lastDayOfMonth = LocalDateTime.of(LocalDate.now().plusMonths(-i), LocalTime.MIN).with(TemporalAdjusters.lastDayOfMonth()).format(formatters);
           params.put("beginTime",firstday);
           params.put("endTime",lastDayOfMonth);
           aAttack.setParams(params);
           Integer thisMonthAttackAmount = this.selectAAttackList(aAttack).size();
           attackAmountEverMonth.add(thisMonthAttackAmount);
        }


        ArrayList<Object> attackMainData = new ArrayList<>();

        //评估数量
        attackMainData.add(totalAttackAmount);
        //昨日新增评估
        attackMainData.add(yesterdayAttackAmount);
        //7日内新增评估
        attackMainData.add(sevenDaysAttacksAmount);
        //高攻击概率数量
        attackMainData.add(highRateAttackAmount);

        //攻击概率分析
        attackMainData.add(attackIndexLevelData);
        //攻击类型分析
        attackMainData.add(attackTypeData);

        //折线图月份
        attackMainData.add(attackMonths);
        //折线图攻击次数
        attackMainData.add(attackAmountEverMonth);

        mmap.put("attackMainData",attackMainData);

        return mmap;
    }
}
